package com.spa.application.service.massagist;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.spa.application.command.massagist.MassagistMyEditCommand;
import com.spa.application.command.massagist.MassagistOnlineCommand;
import com.spa.application.dto.massagist.*;
import com.spa.application.query.massagist.MassagistFinanceQuery;
import com.spa.application.query.massagist.MassagistQuery;
import com.spa.domain.entity.*;
import com.spa.domain.service.*;
import com.spa.infrastructure.enums.dict.massagist.MassagistStatusEnum;
import com.spa.infrastructure.enums.dict.order.OrderIsTransferEnum;
import com.spa.infrastructure.enums.dict.order.OrderOperStatusEnum;
import com.spa.infrastructure.enums.dict.order.OrderStatusEnum;
import com.spa.infrastructure.exception.SpaException;
import com.spa.infrastructure.mapper.MassagistMapperStruct;
import com.spa.infrastructure.mapper.OrderMapperStruct;
import com.spa.infrastructure.mapper.ShopMapperStruct;
import com.spa.infrastructure.repository.condition.MassagistCondition;
import com.spa.infrastructure.repository.condition.MassagistWithdrawRecordCondition;
import com.spa.infrastructure.repository.condition.OrderInfoCondition;
import com.spa.infrastructure.repository.po.MassagistPO;
import com.spa.infrastructure.service.sms.SmsProvider;
import com.spa.infrastructure.service.sms.huaxin.HuaXinUtil;
import com.spa.infrastructure.util.SessionUtil;
import com.spa.infrastructure.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MassagistHomeApplicationService {

    @Autowired
    private MassagistService messagistService;

    @Autowired
    private MassageService massageService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private MassagistOnoffService massagistOnoffService;

    @Autowired
    private ShopService shopService;

    @Autowired
    private MsgAlarmLogService msgAlarmLogService;

    @Autowired
    private MassagistWithdrawRecordService massagistWithdrawRecordService;

    @Autowired
    private ProfitService profitService;

    @Autowired
    private ShopUserService shopUserService;

    @Resource
    private SmsProvider smsProvider;

    public MassagistHomeDTO getMyHomeInfo() {

        Massagist massagistInfo = messagistService.getMassagistInfoByUserId();

        MassagistCondition condition = new MassagistCondition();
        condition.setMassagistId(massagistInfo.getId());
        condition.setUserId(massagistInfo.getUserId());
        //技师信息
        if (!messagistService.massagistExists(condition)) {
            throw new SpaException("无效的技师信息");
        }

        MassagistHomeDTO messagistHomeDTO = MassagistMapperStruct.INSTANCE.entity2HomeDto(massagistInfo);

        Shop shop = shopService.getInfoById(massagistInfo.getShopId());
        MassagistShopDTO massagistShopDTO = ShopMapperStruct.INSTANCE.entity2messagistShopDto(shop);
        massagistShopDTO.setShopScore(shopService.getShopScore(shop.getId()));
        messagistHomeDTO.setShop(massagistShopDTO);

        MassagistOrderDTO messagistOrderDTO = OrderMapperStruct.INSTANCE.orderInfo2OorderInfoDTO(findHomeOrderInfo(messagistHomeDTO.getId(),
                OrderStatusEnum.$20, OrderStatusEnum.$30));
        messagistHomeDTO.setOrderInfoAppointDTO(messagistOrderDTO);

        //可服务项目
        List<MassageServiceEntity> massageServiceEntities = massageService.getServiceByMessageId(messagistHomeDTO.getId());
        if (CollUtil.isNotEmpty(massageServiceEntities)) {
            messagistHomeDTO.setMassageServiceDTOS(MassagistMapperStruct.INSTANCE.entity2DTO(massageServiceEntities));
        }
        return messagistHomeDTO;
    }


    private OrderInfo findHomeOrderInfo(Long massagistId, OrderStatusEnum... statusEnum) {

        OrderInfoCondition orderInfoCondition = new OrderInfoCondition();
        orderInfoCondition.setMassagistId(massagistId);
        orderInfoCondition.setIsTransfer(OrderIsTransferEnum.$0.getCode());
        orderInfoCondition.setStatusList(Arrays.stream(statusEnum).map(OrderStatusEnum::getCode).toList());
        List<OrderInfo> orderInfos = orderService.orderList(orderInfoCondition);
        if (CollUtil.isNotEmpty(orderInfos)) {
            orderInfos = orderInfos.stream().sorted(Comparator
                    // 先按数量降序（由于是降序，nullsFirst()方法会将null值放在后面）
                    .comparing(OrderInfo::getStatus, Comparator.nullsFirst(Integer::compareTo).reversed())
                    // 然后按价格升序（由于是升序，nullsFirst()方法会将null值放在前面）
                    .thenComparing(OrderInfo::getOrderOperStatus, Comparator.nullsFirst(Integer::compareTo).reversed())
                    // 然后按名称降序（如果不设置null值排序规则，字段为null会报错）
                    .thenComparing(OrderInfo::getAppointTime)
            ).toList();
            return orderInfos.get(0);
        }
        return null;
    }

    public boolean online(MassagistOnlineCommand command) {
        Long userId = SessionUtil.getUser().getExtUserId();
        Massagist massagistEdit = MassagistMapperStruct.INSTANCE.command2entity(command);
        massagistEdit.setId(userId);
        massagistOnoffService.saveOnTime(userId);
        massagistEdit.setAppointmentTime(new Date());
        massagistEdit.setStatus(MassagistStatusEnum.$20.getCode());
        return messagistService.optionMyStatus(massagistEdit);
    }

    public boolean offline() {
        Massagist massagistInfo = messagistService.getMassagistInfoByUserId();
        Massagist massagistEdit = new Massagist();
        massagistEdit.setId(massagistInfo.getId());
        if (ObjectUtil.equal(MassagistStatusEnum.$30.getCode(), massagistInfo.getStatus())) {
            throw new SpaException("服务中不可操作");
        }
        massagistOnoffService.saveOffTime(massagistInfo.getId());
        massagistEdit.setAppointmentTime(null);
        massagistEdit.setStatus(MassagistStatusEnum.$10.getCode());
        return messagistService.optionMyStatus(massagistEdit);
    }

    public Massagist getMyInfo(Long messagistId) {
        MassagistCondition condition = new MassagistCondition();
        condition.setMassagistId(messagistId);
        return messagistService.infoById(condition.getMassagistId());
    }

    public boolean myInfoChange(MassagistMyEditCommand command) {
        Massagist massagistInfo = messagistService.getMassagistInfoByUserId();

        MassagistCondition condition = new MassagistCondition();
        condition.setMassagistId(massagistInfo.getId());

        if (!messagistService.massagistExists(condition)) {
            throw new SpaException("无效的技师信息");
        }
        MassagistPO massagistPO = MassagistMapperStruct.INSTANCE.editCommand2Po(command);
        massagistPO.setId(massagistInfo.getId());
        return messagistService.editInfo(massagistPO);
    }

    public MassagistFinanceDTO getMyFinance(MassagistQuery query) {
        Long massagistId = SessionUtil.getUser().getExtUserId();
        Massagist myInfo = getMyInfo(massagistId);
        MassagistFinanceDTO messagistFinanceDTO = MassagistMapperStruct.INSTANCE.entity2FinanceDto(myInfo);
        Date date = new Date();
        String beginDate = DateUtil.beginOfMonth(date).toString(DatePattern.NORM_DATETIME_FORMAT);
        String endDate = DateUtil.endOfMonth(date).toString(DatePattern.NORM_DATETIME_FORMAT);
        MassagistIncomeDetailDTO massagistIncomeDetailDTO = messagistService.getMassagistIncomeDetailDTO(massagistId, beginDate, endDate);
        messagistFinanceDTO.setCurrentPerf(massagistIncomeDetailDTO.getCurrentPerf());
        messagistFinanceDTO.setCurrentIncome(massagistIncomeDetailDTO.getCurrentIncome());
        messagistFinanceDTO.setCashAvailable(getCashAvailable());
        messagistFinanceDTO.setIdentity("20");
        return messagistFinanceDTO;
    }

    public List<MassagistFinanceDetailBaseDTO> getMyFinanceDailyDetails(MassagistFinanceQuery query) {
        Long massagistId = SessionUtil.getUser().getExtUserId();
        //开始日期在结束日期之后
        List<DateTime> dateTimes = DateUtil.rangeToList(query.getStartTime(), query.getEndTime(), DateField.DAY_OF_YEAR);
        return dateTimes.stream().map(dateTime -> {
            MassagistFinanceDetailDTO messagistFinanceDetailBaseDTO = messagistService.getFinanceDetail(massagistId,
                    DateUtil.beginOfDay(dateTime).toString(DatePattern.NORM_DATETIME_FORMAT),
                    DateUtil.endOfDay(dateTime).toString(DatePattern.NORM_DATETIME_FORMAT));
            int flag = ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getCurrentPerf(), 0) +
                    ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getServiceIncome(), 0) +
                    ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getTaxiIncome(), 0) +
                    ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getExtraCount(), 0) +
                    ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getExtraIncome(), 0) +
                    ObjectUtil.defaultIfNull(messagistFinanceDetailBaseDTO.getOrderCount(), 0);
            if (flag != 0) {
                MassagistFinanceDetailBaseDTO massagistFinanceDetailBaseDTO = MassagistMapperStruct.INSTANCE.Finance2FinanceBase(messagistFinanceDetailBaseDTO);
                massagistFinanceDetailBaseDTO.setDetaiData(dateTime);
                return massagistFinanceDetailBaseDTO;
            } else {
                return null;
            }
        }).filter(ObjectUtil::isNotEmpty).sorted(Comparator.comparing(MassagistFinanceDetailBaseDTO::getDetaiData).reversed()).toList();
    }

    public Boolean lonlat(MassagistOnlineCommand command) {
        Long userId = SessionUtil.getUser().getExtUserId();
        Massagist massagistEdit = MassagistMapperStruct.INSTANCE.command2entity(command);
        massagistEdit.setId(userId);
        return messagistService.optionMyStatus(massagistEdit);
    }

    public void touchCall() {
        Massagist massagist = messagistService.getMassagistInfoByUserId();
        // 获取订单信息
        OrderInfo orderInfo = this.findHomeOrderInfo(massagist.getId(), OrderStatusEnum.$30);

        if (ObjectUtil.isNull(orderInfo) || ObjectUtil.notEqual(orderInfo.getOrderOperStatus(), OrderOperStatusEnum.$40.getCode())) {
            log.error("技师触发报警，当前没有进行中的订单信息");
            return;
        }

        String addres = "";
        // 是否上传真实地址
        if (ObjectUtil.isNotNull(orderInfo.getExactLocation())) {
            addres = orderInfo.getExactLocation();
        } else {
            OrderAddress orderClient = orderInfo.getOrderAddress();
            addres = orderClient.getAddress();
        }

        //发送短信给门店负责人
        List<String> list = new ArrayList<>();
        List<ShopUser> shopUsers = shopUserService.queryListByshopId(orderInfo.getShopId());
        if (CollUtil.isNotEmpty(shopUsers)) {
            shopUsers.stream().forEach(shopUser -> {
                if (StringUtils.isNotEmpty(shopUser.getOwnerPhone())) {
                    list.add(shopUser.getOwnerPhone());
                } else {
                    list.add(shopUser.getPhone());
                }
            });
        }

        String content = HuaXinUtil.template5(orderInfo.getOrderCode(), massagist.getName(), massagist.getPhone()
                , addres, orderInfo.getOrderAddress().getPhone());
        smsProvider.sendNotice(list.stream().collect(Collectors.joining(",")), content);

        //记录日志
        msgAlarmLogService.add(orderInfo.getId(), massagist.getId(), addres);
    }


    //获取技师月度财务数据
    public MassagistFinanceDetailDTO getMyFinanceDetails() {
        Long massagistId = SessionUtil.getUser().getExtUserId();
        Date date = new Date();
        String beginDate = DateUtil.beginOfMonth(date).toString(DatePattern.NORM_DATETIME_FORMAT);
        String endDate = DateUtil.endOfMonth(date).toString(DatePattern.NORM_DATETIME_FORMAT);
        return messagistService.getMyFinanceDetails(massagistId, beginDate, endDate);
    }


    public Integer getCashAvailable() {
        Long massagstiId = SessionUtil.getUser().getExtUserId();
        //计算技师总收入
        List<Profit> profits = profitService.queryProfitByMassagistId(massagstiId, null, null);
        if (CollUtil.isNotEmpty(profits)) {
            // 计算技师上个月已经提现的收入
            MassagistWithdrawRecordCondition condition = new MassagistWithdrawRecordCondition();
            condition.setMassagistId(massagstiId);
            List<MassagistWithdrawRecord> massagistWithdrawRecords = massagistWithdrawRecordService.list(condition);
            int massagistSum = massagistWithdrawRecords.stream().map(MassagistWithdrawRecord::getAmount).reduce(Integer::sum).orElse(0);
            int massagistIncome = profits.stream().filter(ObjectUtil::isNotNull).mapToInt(p -> ObjectUtil.isNotNull(p.getMassagistIncome()) ? p.getMassagistIncome() : 0).sum();
            int travelIncome = profits.stream().filter(ObjectUtil::isNotNull).mapToInt(p -> ObjectUtil.isNotNull(p.getTravelPrice()) ? p.getTravelPrice() : 0).sum();
            return Math.max(massagistIncome + travelIncome - massagistSum, 0);
        }
        return 0;
    }

}
